use crate::physical_plan::PhysicalPlanExprArg;
use crate::data_frame::single_data::SingleData;
use crate::run_plan::HandResult;
use crate::data_frame::value::RealValue;

pub fn meta_statistic_record_add(args: &[Box<PhysicalPlanExprArg>], data: &mut SingleData)
                                 -> HandResult {

    if args.len() != 2{
        return HandResult::Err(());
    }

    let key = &args[0];
    let value = &args[1];

    let value = match value.as_ref(){
        PhysicalPlanExprArg::RealValue(value) => {value.to_usize()},
        PhysicalPlanExprArg::ConfValue(value) => {value.to_u64()?.to_usize()},
        PhysicalPlanExprArg::ElementValue(value) => {
            let value = data.data.get_key_value(value)?;
            value.to_usize()
        },
    };

    match key.as_ref(){
        PhysicalPlanExprArg::ConfValue(key) => {
            let t = &key.value;
            if let Some(key) = data.metadata.statistic_record.get_mut(t.as_str()){
                *key = (*key).saturating_add(value);
            }else{
                data.metadata.statistic_record.insert(t.clone(), value);
            }
        },
        PhysicalPlanExprArg::RealValue(key) => {
            let t = key.to_string();
            if let Some(key) = data.metadata.statistic_record.get_mut(t.as_str()){
                *key = (*key).saturating_add(value);
            }else{
                data.metadata.statistic_record.insert(t, value);
            }
        },
        PhysicalPlanExprArg::ElementValue(key) => {
            let key = data.data.get_key_value(key)?;
            let t = key.to_string();
            if let Some(key) = data.metadata.statistic_record.get_mut(t.as_str()){
                *key = (*key).saturating_add(value);
            }else{
                data.metadata.statistic_record.insert(t, value);
            }
        },
    }

    return HandResult::Ok(RealValue::None);
}

pub fn meta_statistic_record_sub(args: &[Box<PhysicalPlanExprArg>], data: &mut SingleData)
                                 -> HandResult {

    if args.len() != 2{
        return HandResult::Err(());
    }

    let key = &args[0];
    let value = &args[1];

    let value = match value.as_ref(){
        PhysicalPlanExprArg::RealValue(value) => {value.to_usize()},
        PhysicalPlanExprArg::ConfValue(value) => {value.to_u64()?.to_usize()},
        PhysicalPlanExprArg::ElementValue(value) => {
            let value = data.data.get_key_value(value)?;
            value.to_usize()
        },
    };

    match key.as_ref(){
        PhysicalPlanExprArg::ConfValue(key) => {
            let t = &key.value;
            if let Some(key) = data.metadata.statistic_record.get_mut(t.as_str()){
                *key = (*key).saturating_sub(value);
            }else{
                data.metadata.statistic_record.insert(t.clone(), 0);
            }
        },
        PhysicalPlanExprArg::RealValue(key) => {
            let t = key.to_string();
            if let Some(key) = data.metadata.statistic_record.get_mut(t.as_str()){
                *key = (*key).saturating_sub(value);
            }else{
                data.metadata.statistic_record.insert(t, 0);
            }
        },
        PhysicalPlanExprArg::ElementValue(key) => {
            let key = data.data.get_key_value(key)?;
            let t = key.to_string();
            if let Some(key) = data.metadata.statistic_record.get_mut(t.as_str()){
                *key = (*key).saturating_sub(value);
            }else{
                data.metadata.statistic_record.insert(t, 0);
            }
        },
    }

    return HandResult::Ok(RealValue::None);
}